home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
src
/
haeberli
/
objtools
/
tlsplit.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
15KB
|
747 lines
/*
* Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
* the contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to restrictions
* as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
* and Computer Software clause at DFARS 252.227-7013, and/or in similar or
* successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
* rights reserved under the Copyright Laws of the United States.
*/
/*
* tlsplit -
* Split all intersecting triangles in a triangle list.
*
* Paul Haeberli - 1991
*/
#include "math.h"
#include "stdio.h"
#include "gl.h"
#include "device.h"
#include "trilist.h"
#include "vect.h"
#include "simple.h"
#define WSIZE (200)
#define ASPECT (3.0/2.0)
#define ALMOSTPLANAR (0.9999)
#define USEDOUBLES
#ifdef USEDOUBLES
#define TOLERANCE (0.00000000001)
#define VECT dvect
#define FLOAT double
#define TRINORMAL(a,b,c,d,e) dtrinormal(a,b,c,d,e)
#define FLERP(a,b,c) dlerp(a,b,c)
#define VLERP(a,b,c,d) dvlerp(a,b,c,d)
#define VPLANE(a,b,c) dvplane(a,b,c)
#define V3F(a) v3d((double *)a)
#define VDOT(a,b) dvdot(a,b)
#else
#define TOLERANCE (0.0000001)
#define VECT vect
#define FLOAT float
#define TRINORMAL(a,b,c,d,e) trinormal(a,b,c,d,e)
#define FLERP(a,b,c) flerp(a,b,c)
#define VLERP(a,b,c,d) vlerp(a,b,c,d)
#define VPLANE(a,b,c) vplane(a,b,c)
#define V3F(a) v3f((float *)a)
#define VDOT(a,b) vdot(a,b)
#endif
typedef struct tile {
struct tile *next;
FLOAT xmin, xmax;
FLOAT ymin, ymax;
FLOAT zmin, zmax;
VECT plane;
VECT edgeeq[3];
VECT pos[3];
long col[3];
int backfacing;
} tile;
#define INTER_NONE 0
#define INTER_TOUCHES 1
#define INTER_COVERS 2
float frand();
tile *tiles;
FILE *outf;
FLOAT curwidth;
int ntiles;
FLOAT cthresh;
tile *ysortlist();
tile *splittri();
FLOAT cdist();
FLOAT colordel();
unsigned long clerp(i1,i2,param)
unsigned long i1, i2;
FLOAT param;
{
int r1, g1, b1, a1;
int r2, g2, b2, a2;
int r, g, b, a;
unsigned long ret;
r1 = (i1>>24)&0xff;
g1 = (i1>>16)&0xff;
b1 = (i1>>8)&0xff;
a1 = (i1>>0)&0xff;
r2 = (i2>>24)&0xff;
g2 = (i2>>16)&0xff;
b2 = (i2>>8)&0xff;
a2 = (i2>>0)&0xff;
r = lerp(r1,r2,param);
g = lerp(g1,g2,param);
b = lerp(b1,b2,param);
a = lerp(a1,a2,param);
ret = (r<<24)+(g<<16)+(b<<8)+(a<<0);
return ret;
}
/*
* fast alloc for tiles.
*
*
*/
#define NINCHUNK 300
tile *ftiles;
tile *tilemalloc()
{
tile *t;
int i;
if(!ftiles) {
t = (tile *)malloc(NINCHUNK*sizeof(tile));
for(i=0; i<NINCHUNK; i++)
freetile(t++);
}
t = ftiles;
ftiles = ftiles->next;
t->next = 0;
return t;
}
freetile(t)
tile *t;
{
if( t ) {
t->next = ftiles;
ftiles = t;
}
}
FLOAT edgedist2d(edgeeq,pos)
VECT *edgeeq, *pos;
{
return (edgeeq->x*pos->x) + (edgeeq->y*pos->y) + edgeeq->w;
}
FLOAT planedist3d(planeeq,pos)
VECT *planeeq, *pos;
{
return (planeeq->x*pos->x) +
(planeeq->y*pos->y) +
(planeeq->z*pos->z) + planeeq->w;
}
tile *readtilelist(name)
char *name;
{
int i, j, ntri;
trilisttri tri;
tile *tiles, *atile;
VECT norm, temp;
FLOAT dx, dy, w, mag;
ntri = tlopen(name);
tiles = 0;
for(i=0; i<ntri; i++) {
tlread(&tri);
atile = tilemalloc();
atile->pos[0].x = tri.x0;
atile->pos[0].y = tri.y0;
atile->pos[0].z = tri.z0;
atile->pos[1].x = tri.x1;
atile->pos[1].y = tri.y1;
atile->pos[1].z = tri.z1;
atile->pos[2].x = tri.x2;
atile->pos[2].y = tri.y2;
atile->pos[2].z = tri.z2;
atile->col[0] = tri.c0&0xffffff;
atile->col[1] = tri.c1&0xffffff;
atile->col[2] = tri.c2&0xffffff;
if(TRINORMAL(atile->pos+0,atile->pos+1,atile->pos+2,&norm,TOLERANCE/50.0)) {
if(norm.z<0.0) {
norm.x = -norm.x;
norm.y = -norm.y;
norm.z = -norm.z;
temp = atile->pos[1];
atile->pos[1] = atile->pos[2];;
atile->pos[2] = temp;
atile->backfacing = 1;
} else {
atile->backfacing = 0;
}
VPLANE(&norm,atile->pos+0,&atile->plane);
tiledomain(atile);
atile->next = tiles;
tiles = atile;
} else {
fprintf(stderr,"zero tri found!!\n");
}
}
tlclose();
tiles = (tile *)ysortlist(tiles);
return tiles;
}
tiledomain(atile)
tile *atile;
{
int j;
FLOAT dx, dy, w, mag;
for(j=0; j<3; j++) {
dx = atile->pos[(j+1)%3].y-atile->pos[j].y;
dy = atile->pos[(j+1)%3].x-atile->pos[j].x;
mag = sqrt(dx*dx+dy*dy);
dx = dx/mag;
dy = -dy/mag;
w = dx*atile->pos[j].x+dy*atile->pos[j].y;
atile->edgeeq[j].x = dx;
atile->edgeeq[j].y = dy;
atile->edgeeq[j].w = -w;
}
atile->xmin = atile->xmax = atile->pos[0].x;
atile->ymin = atile->ymax = atile->pos[0].y;
atile->zmin = atile->zmax = atile->pos[0].z;
for(j=1; j<3; j++) {
if(atile->xmin>atile->pos[j].x)
atile->xmin=atile->pos[j].x;
if(atile->xmax<atile->pos[j].x)
atile->xmax=atile->pos[j].x;
if(atile->ymin>atile->pos[j].y)
atile->ymin=atile->pos[j].y;
if(atile->ymax<atile->pos[j].y)
atile->ymax=atile->pos[j].y;
if(atile->zmin>atile->pos[j].z)
atile->zmin=atile->pos[j].z;
if(atile->zmax<atile->pos[j].z)
atile->zmax=atile->pos[j].z;
}
}
writetilelist(name,tiles)
char *name;
tile *tiles;
{
trilisttri tltri;
short magic;
FILE *outf;
outf = fopen(name,"w");
if(!outf) {
fprintf(stderr,"tlsplit: can't open output file\n");
exit(1);
}
magic = TLMAGIC;
fwrite(&magic,sizeof(short),1,outf);
while(tiles) {
tltri.x0 = tiles->pos[0].x;
tltri.y0 = tiles->pos[0].y;
tltri.z0 = tiles->pos[0].z;
tltri.c0 = tiles->col[0];
tltri.x1 = tiles->pos[1].x;
tltri.y1 = tiles->pos[1].y;
tltri.z1 = tiles->pos[1].z;
tltri.c1 = tiles->col[1];
tltri.x2 = tiles->pos[2].x;
tltri.y2 = tiles->pos[2].y;
tltri.z2 = tiles->pos[2].z;
tltri.c2 = tiles->col[2];
fwrite(&tltri,sizeof(trilisttri),1,outf);
tiles = tiles->next;
}
fclose(outf);
}
drawtilelist(tlist)
tile *tlist;
{
reshapeviewport();
ortho(-1.1,1.1,-1.1,1.1,-2.0,2.0);
rgb(1.0,1.0,1.0);
clear();
rgb(1.0,0.0,0.0);
while(tlist) {
drawtile(tlist);
tlist = tlist->next;
}
}
main(argc,argv)
int argc;
char **argv;
{
short val;
int i;
cthresh = 0.10;
if(argc<2) {
fprintf(stderr,"usage: tlsplit input.tl [-t 0.10]\n");
exit(1);
}
for(i=2; i<argc; i++) {
if(argv[i][0] == '-') {
switch(argv[i][1]) {
case 't':
i++;
cthresh = atof(argv[i]);
break;
}
}
}
prefposition(0,(3*WSIZE)-1,50,50+(2*WSIZE)-1);
foreground();
winopen("tlsplit");
qdevice(LEFTMOUSE);
qdevice(MIDDLEMOUSE);
RGBmode();
gconfig();
deflinestyle(1,0x3030);
rgb(0.5,0.5,0.5);
clear();
ntiles = 0;
tiles = readtilelist(argv[1]);
drawtilelist(tiles);
dosplit(tiles);
writetilelist(argv[2],tiles);
exit(0);
}
printtile(t)
tile *t;
{
int i;
for(i=0; i<3; i++) {
fprintf(stderr,"t%d: %f %f %f\n",
i,t->pos[i].x,t->pos[i].y,t->pos[i].z);
}
fprintf(stderr,"\n");
}
dosplit(tlist)
tile *tlist;
{
tile *tl, *otl, t1, t2, t3;
tile *stl, *ntl;
int interc;
FLOAT top;
/* use graphics for now */
reshapeviewport();
ortho(-1.0,1.0,-1.0,1.0,-2.0,2.0);
rgb(1.0,1.0,1.0);
clear();
/* find all the places where two triangles intersect */
rgb(0.0,0.0,0.0);
linewidth(1);
interc = 0;
tl = tlist;
while(tl) {
otl = tl;
while(otl->next) {
#ifdef LATER
if(otl->next->ymin>tl->ymax)
break;
#endif
if(tritriinter(tl,otl->next)) {
fprintf(stderr,"before split");
stl = splittri(otl->next,&tl->plane);
fprintf(stderr,"i");
if(stl) {
ntl = stl;
while(ntl->next) {
ntl = ntl->next;
fprintf(stderr,".");
}
ntl->next = otl->next;
otl->next = stl;
otl = ntl;
}
interc++;
}
otl = otl->next;
}
tl = tl->next;
}
fprintf(stderr,"\nTotal intersections %d\n",interc);
}
#define E0 0x1
#define E1 0x2
#define E2 0x4
tile *splittri(try,plane)
tile *try;
VECT *plane;
{
FLOAT pd[3], d, dp, dm, param;
tile *ret, *newl;
int intercode, vr;
int v0, v1, v2;
long ic0, ic1;
VECT ip0, ip1;
dp = -plane->w;
dm = -plane->w;
d = -plane->w;
pd[0] = VDOT(plane,&try->pos[0]);
pd[1] = VDOT(plane,&try->pos[1]);
pd[2] = VDOT(plane,&try->pos[2]);
ret = 0;
fprintf(stderr," p is %f vals are %f %f %f\n",d, pd[0],pd[1],pd[2]);
if(pd[0]<dp && pd[1]<dp && pd[2]<dp) {
fprintf(stderr,"bad poop1\n");
newl = tilemalloc();
*newl = *try;
newl->next = 0;
return newl;
} else if(pd[0]>dm && pd[1]>dm && pd[2]>dm) {
fprintf(stderr,"bad poop2\n");
newl = tilemalloc();
*newl = *try;
newl->next = 0;
return newl;
} else {
intercode = 0;
if(pd[0]<d && pd[1]>d) {
intercode |= E0;
} else if(pd[0]>d && pd[1]<d) {
intercode |= E0;
}
if(pd[1]<d && pd[2]>d) {
intercode |= E1;
} else if(pd[1]>d && pd[2]<d) {
intercode |= E1;
}
if(pd[2]<d && pd[0]>d) {
intercode |= E2;
} else if(pd[2]>d && pd[0]<d) {
intercode |= E2;
}
vr = 0;
switch(intercode) {
case E2:
vr++;
case E1:
vr++;
case E0:
v0 = (0+vr)%3;
v1 = (1+vr)%3;
v2 = (2+vr)%3;
param = (d-pd[v0])/(pd[v1]-pd[v0]);
VLERP(&try->pos[v0],&try->pos[v1],&ip0,param);
ic0 = clerp(try->col[v0],try->col[v1],param);
newl = tilemalloc(); /* neg side */
newl->pos[v0] = try->pos[v0];
newl->col[v0] = try->col[v0];
newl->pos[v1] = ip0;
newl->col[v1] = ic0;
newl->pos[v2] = try->pos[v2];
newl->col[v2] = try->col[v2];
tiledomain(newl);
newl->plane = try->plane;
newl->next = ret;
ret = newl;
newl = tilemalloc(); /* pos side */
newl->pos[v0] = ip0;
newl->col[v0] = ic0;
newl->pos[v1] = try->pos[v1];
newl->col[v1] = try->col[v1];
newl->pos[v2] = try->pos[v2];
newl->col[v2] = try->col[v2];
tiledomain(newl);
newl->plane = try->plane;
newl->next = ret;
ret = newl;
return ret;
break;
case E2|E0:
vr++;
case E1|E2:
vr++;
case E0|E1:
v0 = (0+vr)%3;
v1 = (1+vr)%3;
v2 = (2+vr)%3;
param = (d-pd[v0])/(pd[v1]-pd[v0]);
VLERP(&try->pos[v0],&try->pos[v1],&ip0,param);
ic0 = clerp(try->col[v0],try->col[v1],param);
param = (d-pd[v2])/(pd[v1]-pd[v2]);
VLERP(&try->pos[v2],&try->pos[v1],&ip1,param);
ic1 = clerp(try->col[v2],try->col[v1],param);
newl = tilemalloc(); /* neg side */
newl->pos[v0] = try->pos[v0];
newl->col[v0] = try->col[v0];
newl->pos[v1] = ip0;
newl->col[v1] = ic0;
newl->pos[v2] = try->pos[v2];
newl->col[v2] = try->col[v2];
tiledomain(newl);
newl->plane = try->plane;
newl->next = ret;
ret = newl;
newl = tilemalloc(); /* neg side */
newl->pos[v0] = ip0;
newl->col[v0] = ic0;
newl->pos[v1] = ip1;
newl->col[v1] = ic1;
newl->pos[v2] = try->pos[v2];
newl->col[v2] = try->col[v2];
tiledomain(newl);
newl->plane = try->plane;
newl->next = ret;
ret = newl;
newl = tilemalloc(); /* pos side */
newl->pos[v0] = ip0;
newl->col[v0] = ic0;
newl->pos[v1] = try->pos[v1];
newl->col[v1] = try->col[v1];
newl->pos[v2] = ip1;
newl->col[v2] = ic1;
tiledomain(newl);
newl->plane = try->plane;
newl->next = ret;
ret = newl;
return ret;
break;
default:
fprintf(stderr,"strange code %d\n",intercode);
return ret;
}
}
}
bbox3d(e,t)
tile *e;
tile *t;
{
if(e->xmax<=t->xmin)
return 0;
if(t->xmax<=e->xmin)
return 0;
if(e->ymax<=t->ymin)
return 0;
if(t->ymax<=e->ymin)
return 0;
if(e->zmax<=t->zmin)
return 0;
if(t->zmax<=e->zmin)
return 0;
return 1;
}
posinside(p,t)
VECT *p;
tile *t;
{
int i;
FLOAT d;
for(i=0; i<3; i++) {
d = edgedist2d(t->edgeeq+i,p);
if(d>-TOLERANCE)
return 0;
}
return 1;
}
tritriinter(t1,t2)
tile *t1, *t2;
{
FLOAT d[3];
int i, l, g, il, ig, al, ag;
int lpos[3], gpos[3];
int ngood, ngot;
FLOAT goodparam[6], dot;
VECT *goodpos1[6], *goodpos2[6];
tile *goodtri[6];
VECT pos;
if(!bbox3d(t1,t2))
return 0;
dot = VDOT(&t1->plane,&t2->plane);
if(dot<0.0)
dot = -dot;
if(dot>ALMOSTPLANAR)
return 0;
ngood = 0;
l = g = 0;
for(i=0; i<3; i++) {
d[i] = planedist3d(&t1->plane,&t2->pos[i]);
if(d[i]<-TOLERANCE)
lpos[l++] = i;
else if(d[i]>TOLERANCE)
gpos[g++] = i;
}
if((l==0) || (g==0))
return 0;
for(il=0; il<l; il++) {
for(ig=0; ig<g; ig++) {
al = lpos[il];
ag = gpos[ig];
goodparam[ngood] = d[al]/(d[al]-d[ag]);
goodpos1[ngood] = &t2->pos[al];
goodpos2[ngood] = &t2->pos[ag];
goodtri[ngood] = t1;
ngood++;
}
}
l = g = 0;
for(i=0; i<3; i++) {
d[i] = planedist3d(&t2->plane,&t1->pos[i]);
if(d[i]<-TOLERANCE)
lpos[l++] = i;
else if(d[i]>TOLERANCE)
gpos[g++] = i;
}
if((l==0) || (g==0))
return 0;
for(il=0; il<l; il++) {
for(ig=0; ig<g; ig++) {
al = lpos[il];
ag = gpos[ig];
goodparam[ngood] = d[al]/(d[al]-d[ag]);
goodpos1[ngood] = &t1->pos[al];
goodpos2[ngood] = &t1->pos[ag];
goodtri[ngood] = t2;
ngood++;
}
}
ngot = 0;
for(g=0; g<ngood; g++) {
VLERP(goodpos1[g],goodpos2[g],&pos,goodparam[g]);
if(posinside(&pos,goodtri[g])) {
ngot++;
if(ngot == 2) {
return 1;
}
}
}
return 0;
}
couldhide(e,t)
tile *e;
tile *t;
{
if(t->zmax<=e->zmin)
return 0;
else
return 1;
}
drawtile(t)
tile *t;
{
bgnclosedline();
V3F(t->pos+0);
V3F(t->pos+1);
V3F(t->pos+2);
endclosedline();
}
compar(p0,p1)
tile **p0, **p1;
{
FLOAT y0, y1;
y0 = (*p0)->ymin;
y1 = (*p1)->ymin;
if(y0<y1)
return 1;
if(y0==y1)
return 0;
else
return -1;
}
tile *ysortlist(tiles)
tile *tiles;
{
tile *t, **all, **tpp;
int i, n;
n = 0;
t = tiles;
while(t) {
t = t->next;
n++;
}
all = (tile **)malloc(n*sizeof(tile*));
t = tiles;
tpp = all;
while(t) {
*tpp++ = t;
t = t->next;
}
qsort(all,n,sizeof(tile *),compar);
t = 0;
tpp = all;
while(n--) {
(*tpp)->next = t;
t = *tpp++;
}
free(all);
return t;
}
dv3f(d)
double d[3];
{
float f[3];
f[0] = d[0];
f[1] = d[1];
f[2] = d[2];
v3f(f);
}